package me.zhengjie.spider.util.service;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.config.FileProperties;
import me.zhengjie.exception.FileDownloadException;
import me.zhengjie.spider.common.SpiderConstant;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.client.RestTemplate;

import javax.validation.constraints.NotNull;
import java.io.File;
import java.nio.file.Files;

/**
 * @author 雨来
 */
@Slf4j
@Data
public class FileDownloader {

    private RestTemplate restTemplate;
    private FileProperties fileProperties;
    private Boolean isActive;

    private final static Integer DEFAULT_RETRY_TIME = 3;

    public void download(String remoteUrl, String localUrl, Integer maxReTry) {
        File localFile = new File(localUrl);
        // 文件已存在，跳过下载
        if (localFile.exists()) {
            return;
        }
        if (!localFile.getParentFile().exists()) {
            boolean mkdir = localFile.getParentFile().mkdirs();
            log.info("文件路径[{}]不存在， 创建{}", localUrl, (mkdir ? "成功" : "失败"));
        }
        int reTry = 1;
        while (true) {
            ResponseEntity<File> responseEntity = restTemplate.execute(remoteUrl, HttpMethod.GET, null, response -> {
                if (response.getStatusCode() == HttpStatus.OK) {
                    FileCopyUtils.copy(response.getBody(), Files.newOutputStream(localFile.toPath()));
                    return ResponseEntity.status(response.getStatusCode()).headers(response.getHeaders()).body(localFile);
                }
                return null;
            });
            if (responseEntity != null && responseEntity.getStatusCode() == HttpStatus.OK) {
                log.info("文件[{}]下载完成", localUrl);
                break;
            }
            reTry++;
            if (reTry >= maxReTry) {
                if (localFile.exists()) {
                    localFile.delete();
                }
                log.error("下载远程文件失败！remoteUrl: {}", remoteUrl);
                break;
            }
        }
    }

    public void downloadJpg(String remoteUrl, @NotNull String suffixDir, Integer maxReTry) {
        String baseUrl = fileProperties.getPath().getPath();
        String preDir = baseUrl.endsWith(SpiderConstant.FOLDER_DIR) ? baseUrl : baseUrl + SpiderConstant.FOLDER_DIR;
        String localUrl = preDir + suffixDir;
        localUrl = localUrl.endsWith(SpiderConstant.FOLDER_DIR) ? localUrl + SpiderConstant.FILE_NAME_JPG : localUrl + SpiderConstant.FOLDER_DIR + SpiderConstant.FILE_NAME_JPG;
        this.download(remoteUrl, localUrl, maxReTry);
    }

    public void downloadComicJpg(String remoteUrl, @NotNull String suffixDir, String fileName, Integer maxReTry) {
        String baseUrl = fileProperties.getPath().getPath();
        String preDir = baseUrl.endsWith(SpiderConstant.FOLDER_DIR) ? baseUrl : baseUrl + SpiderConstant.FOLDER_DIR;
        String localUrl = preDir + suffixDir;
        localUrl = localUrl.endsWith(SpiderConstant.FOLDER_DIR) ? localUrl + fileName + SpiderConstant.FOLDER_DIR + SpiderConstant.TYPE_JPG : localUrl + SpiderConstant.FOLDER_DIR + fileName + SpiderConstant.FOLDER_DIR + SpiderConstant.TYPE_JPG;
        this.download(remoteUrl, localUrl, maxReTry);
    }

    public void downloadM3U8(String remoteUrl, @NotNull String suffixDir, Integer maxReTry, String tsNameRule) {
        String baseUrl = fileProperties.getPath().getPath();
        String preDir = baseUrl.endsWith(SpiderConstant.FOLDER_DIR) ? baseUrl : baseUrl + SpiderConstant.FOLDER_DIR;
        suffixDir = suffixDir.startsWith(SpiderConstant.FOLDER_DIR) ? suffixDir.replaceFirst(SpiderConstant.FOLDER_DIR, "") : suffixDir;
        String localUrl = preDir + suffixDir;
        localUrl = localUrl.endsWith(SpiderConstant.FOLDER_DIR) ? localUrl + SpiderConstant.FILE_NAME_M3U8 : localUrl + SpiderConstant.FOLDER_DIR + SpiderConstant.FILE_NAME_M3U8;
        this.download(remoteUrl, localUrl, maxReTry);
    }

    public void downloadJpg(String remoteUrl, @NotNull String suffixDir) {
        try {
            this.downloadJpg(remoteUrl, suffixDir, DEFAULT_RETRY_TIME);
        } catch (Exception e) {
            log.error("文件{}下载异常", remoteUrl);
            throw new FileDownloadException("文件" + remoteUrl + "下载异常");
        }
    }

    public void downloadComicJpg(String remoteUrl, @NotNull String suffixDir, String fileName) {
        try {
            this.downloadComicJpg(remoteUrl, suffixDir, fileName, DEFAULT_RETRY_TIME);
        } catch (Exception e) {
            log.error("文件{}下载异常", remoteUrl);
            throw new FileDownloadException("文件" + remoteUrl + "下载异常");
        }
    }

    public void downloadM3U8(String remoteUrl, @NotNull String suffixDir, String tsNameRule) {
        try {
            this.downloadM3U8(remoteUrl, suffixDir, DEFAULT_RETRY_TIME, tsNameRule);
        } catch (Exception e) {
            log.error("文件{}下载异常", remoteUrl);
            throw new FileDownloadException("文件" + remoteUrl + "下载异常");
        }
    }
}
